﻿using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Common.Consul
{
    /*
        使用方法如下
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddConsul();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseConsul();
        }

    consulconfig.json文件内容如下：
    {
      "ConsulAddress": "http://127.0.0.1:8500", //consul 服务器地址
      "ServiceName": "OcelotTest", //服务名称，ApiGateway中配置的ServiceName对应这里
      "HealthCheck": "/api/Health", //健康检查地址
      "ServiceAddress": "https://localhost:44357" //webapi 地址
    }
     */
    /// <summary>
    /// consul服务注册扩展类
    /// </summary>
    public static class ConsulRegistrationExtensions
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="service"></param>
        public static void AddConsul(this IServiceCollection service)
        {
            // 读取服务配置文件
            var config = new ConfigurationBuilder().AddJsonFile("consulconfig.json").Build();
            service.Configure<ConsulServiceOptions>(config);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseConsul(this IApplicationBuilder app)
        {
            // 获取主机生命周期管理接口
            var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

            // 获取服务配置项
            var serviceOptions = app.ApplicationServices.GetRequiredService<IOptions<ConsulServiceOptions>>().Value;

            // 服务ID必须保证唯一
            serviceOptions.ServiceId = Guid.NewGuid().ToString();

            var consulClient = new ConsulClient(configuration =>
            {
                //服务注册的地址，集群中任意一个地址
                configuration.Address = new Uri(serviceOptions.ConsulAddress);
            });

            // 获取当前服务地址和端口，配置方式
            var uri = new Uri(serviceOptions.ServiceAddress);

            // 节点服务注册对象
            var registration = new AgentServiceRegistration()
            {
                ID = serviceOptions.ServiceId,
                Name = serviceOptions.ServiceName,// 服务名
                Address = uri.Host,
                Port = uri.Port, // 服务端口
                Check = new AgentServiceCheck
                {
                    // 注册超时
                    Timeout = TimeSpan.FromSeconds(5),
                    // 服务停止多久后注销服务
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                    // 健康检查地址
                    HTTP = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceOptions.HealthCheck}",
                    // 健康检查时间间隔
                    Interval = TimeSpan.FromSeconds(10),
                }
            };
            // 注册服务
            consulClient.Agent.ServiceRegister(registration).Wait();

            // 应用程序终止时，注销服务
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(serviceOptions.ServiceId).Wait();
            });
            return app;
        }
    }
}
